package win.lioil.bluetooth.ble;

import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.AudioTrack;
import android.media.MediaRecorder;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Toast;


import androidx.annotation.RequiresApi;

import com.cyf.demo.opus.JniClient;
import com.xltt.bluetoothlib.ble.BleManager;
import com.xltt.bluetoothlib.ble.DataPackage;
import com.xltt.bluetoothlib.ble.event.OnChangeEvent;
import com.xltt.bluetoothlib.ble.utils.Command;
import com.xltt.bluetoothlib.ble.utils.HexUtil;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import win.lioil.bluetooth.R;
import win.lioil.bluetooth.util.ByteUtils;
import win.lioil.bluetooth.util.OpusUtil;


/**
 * BLE服务端(从机/外围设备/peripheral)
 */
public class BleServerActivity1 extends Activity implements DataPackage.OnDataPackageListener{

    private static final String TAG = "zhanghui";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_bleserver);
        regBluethSwitch(this);
    }


    @RequiresApi(api = Build.VERSION_CODES.M)
    public void testBtn(View view){
        switch (view.getId()){
            case R.id.open:
                BleManager.getInstance(this).initGattService().setDataPackageListent(this);
                break;
            case R.id.close_ads:
                BleManager.getInstance(this).stopAdvertising();
                break;
            case R.id.open_ads:
                BleManager.getInstance(this).startAdvertising();
                break;
            case R.id.send_test_data:
                sendTestData();
                break;
            case R.id.send_sound_data:
                startVoiceToIntercom();
                break;
            case R.id.end_sound_data:
                stopVoiceToIntercom();
                break;
        }
    }

    /**
     * 注册监听蓝牙开关
     * @param context
     */
    private void regBluethSwitch(Context context){
        Log.i(TAG,"初始化，蓝牙开关监听 " );
        IntentFilter mIntentFilter = new IntentFilter();
        mIntentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
        context.registerReceiver(mBluethReceiver,mIntentFilter);
    }

    /**
     * 注销蓝牙开关
     * @param context
     */
    private void unregBluethSwitch(Context context){
        Log.i(TAG,"销毁，蓝牙开关监听 " );
        context.unregisterReceiver(mBluethReceiver);
    }

    /**
     * 监听蓝牙打开与关闭状态
     */
    private BroadcastReceiver mBluethReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,0);
            switch (state){
                case BluetoothAdapter.STATE_TURNING_ON:
                    Log.i(TAG,"蓝牙正在打开");
                    break;
                case BluetoothAdapter.STATE_ON:
                    Log.i(TAG,"蓝牙已打开");
                    BleManager.getInstance(BleServerActivity1.this).initGattService().setDataPackageListent(BleServerActivity1.this);
                    break;
                case BluetoothAdapter.STATE_TURNING_OFF:
                    Log.i(TAG,"蓝牙正在关闭");
                    BleManager.getInstance(BleServerActivity1.this).destroyGattService();
                    break;
                case BluetoothAdapter.STATE_OFF:
                    Log.i(TAG,"蓝牙已关闭");
                    break;
            }
        }
    };


    /**
     * 响应手机端
     */
    public void respnseData(){
        //主指令
        byte[] cmd = new byte[]{Command.device_info_notify};
        //包下标
        byte[] index = new byte[]{1};
        //这个就是你响应的内容
        byte[] packetData = new byte[0];
        packetData = DataPackage.add(packetData, new byte[]{0x01}, 0, 1);//设备基本信息
        packetData = DataPackage.add(packetData, new byte[]{0x01}, 0, 1);//响应状态
        packetData = DataPackage.add(packetData, new byte[]{0x01}, 0, 1);//版本信息1
        packetData = DataPackage.add(packetData, new byte[]{0x01}, 0, 2);//版本信息2
        packetData = DataPackage.add(packetData, new byte[]{0x01}, 0, 3);//版本信息3
        packetData = DataPackage.add(packetData, new byte[]{0x01}, 0, 7);//版本信息4

        packetData = DataPackage.add(packetData, new byte[]{0x01}, 0, 1);//ID号1
        packetData = DataPackage.add(packetData, new byte[]{0x01}, 0, 2);//ID号2
        packetData = DataPackage.add(packetData, new byte[]{0x01}, 0, 10);//ID号.....10

        //总协议包
        byte[] sendPacket = DataPackage.sendPacket(cmd,index,packetData);
        Log.i("BleManager","点击发送包 = " + Arrays.toString(DataPackage.getHexStrings(sendPacket)));
        //发送包内容到手机端
        BleManager.getInstance(BleServerActivity1.this).sendClientData(sendPacket);
    }

    /**
     * 发送测试数据
     */
    private void sendTestData(){
        byte[] cmd = new byte[]{Command.device_info_notify};
        byte[] index = new byte[]{1};
        byte[] packetData = new byte[0];
        packetData = DataPackage.add(packetData, new byte[]{Command.device_info_notify_frequency_update}, 0, 1);//频率设置
        packetData = DataPackage.add(packetData, HexUtil.intToByteLittle(402), 0, 4);//频率设置值
        byte[] sendPacket = DataPackage.sendPacket(cmd,index,packetData);
        Log.i("BleManager","点击发送包 = " + Arrays.toString(DataPackage.getHexStrings(sendPacket)));
        BleManager.getInstance(BleServerActivity1.this).sendClientData(sendPacket);
    }

    /**
     * 发送开始音频数据
     */
    private boolean sendStartSoundRecording(byte[] newPacket){
        byte[] cmd = new byte[]{Command.audio_data_send};
        byte[] index = new byte[]{1};
        //开始音频内容
        byte[] packetData = new byte[0];
        packetData = DataPackage.add(packetData, new byte[]{0x00}, 0, 1);//模式
        packetData = DataPackage.add(packetData, new byte[]{0x00}, 0, 1);//数据包结束标示
        packetData = DataPackage.add(packetData, HexUtil.shortToByteLittle((short) 0), 0, 2);//数据包结束标示,后续要添加正确索引
        packetData = DataPackage.add(packetData, HexUtil.shortToByteLittle((short) newPacket.length), 0, 2);//可变数据长度
        packetData = DataPackage.add(packetData, newPacket, 0, newPacket.length);//音频数据
        byte[] sendPacket = DataPackage.sendPacket(cmd,index,packetData);
        Log.i("BleManager","发送第一个音频数据包 = " + Arrays.toString(DataPackage.getHexStrings(sendPacket)));
        return BleManager.getInstance(BleServerActivity1.this).sendClientData(sendPacket);
    }

    /**
     * 发送结束音频数据
     */
    private boolean sendStopSoundRecording(){
        byte[] cmd = new byte[]{Command.audio_data_send};
        byte[] index = new byte[]{1};
        //开始音频内容
        byte[] packetData = new byte[0];
        packetData = DataPackage.add(packetData, new byte[]{0x00}, 0, 1);//模式
        packetData = DataPackage.add(packetData, new byte[]{0x01}, 0, 1);//数据包结束标示
        packetData = DataPackage.add(packetData, HexUtil.shortToByteLittle((short) 0), 0, 2);//数据包结束标示,后续要添加正确索引
        packetData = DataPackage.add(packetData, HexUtil.shortToByteLittle((short) 0), 0, 2);//可变数据长度
        byte[] sendPacket = DataPackage.sendPacket(cmd,index,packetData);
        Log.i("BleManager","发送第一个音频数据包 = " + Arrays.toString(DataPackage.getHexStrings(sendPacket)));
        return BleManager.getInstance(BleServerActivity1.this).sendClientData(sendPacket);
    }


    @Override
    protected void onDestroy() {
        BleManager.getInstance(BleServerActivity1.this).destroyGattService();
        unregBluethSwitch(this);
        super.onDestroy();
    }


    @RequiresApi(api = Build.VERSION_CODES.M)
    @Override
    public void OnDataPackage(OnChangeEvent changeEvent) {
        byte[] responseByte = changeEvent.getRequestBytes();
        String[] responseToStr = HexUtil.getHexStrings(responseByte);

        Log.e(TAG, "收到BleManager库数据，客户端写入Characteristic[" + changeEvent.getCharacteristic().getUuid() + "]:\n" + Arrays.toString(responseToStr));
        byte[] packetLength = DataPackage.getPacketLength(responseByte);
        byte[] command = DataPackage.getCommand(responseByte);
        byte[] secondaryCommand = DataPackage.getSecondaryCommand(responseByte);
        byte[] bodyData = DataPackage.getBodyData(responseByte);

        Log.e(TAG, "收到BleManager库数据,解析客户端写入数据域包长度 = " + Arrays.toString(DataPackage.getHexStrings(packetLength)));
        Log.e(TAG, "收到BleManager库数据,解析客户端写入一级指令 = " + Arrays.toString(DataPackage.getHexStrings(command)));
        Log.e(TAG, "收到BleManager库数据,解析客户端写入二级指令 = " + Arrays.toString(DataPackage.getHexStrings(secondaryCommand)));
        Log.e(TAG, "收到BleManager库数据,解析客户端写入body = " + Arrays.toString(DataPackage.getHexStrings(bodyData)));
        if(command[0] == Command.audio_data_revice){
            if(secondaryCommand[0] == Command.audio_data_revice_start){
                Log.e(TAG, "---------------------收到手机端音频数据请求开始---------------------");
            }else if(secondaryCommand[0] == Command.audio_data_revice_end){
                mAudioAdcDataQueue.clear();
                mAudioPlayThread.interrupt();
                mAudioPlayThread = null;
                Log.e(TAG, "---------------------收到手机端音频数据请求结束---------------------");
            }else{
                Log.e(TAG, "收到手机端音频数据包长度 = " + bodyData.length);
                analysisData(bodyData);
            }
        }

    }

    @Override
    public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {

    }


    private boolean isRecord = false;
    private boolean isPlay = false;
    private int totalLength = 0;
    private int sendCount = 0;
    private int opusCount = 0;
    private boolean isContinuePage = false;

//    private static final String RECEIVE_VOICE_PATH = App.getContext().getExternalFilesDir("fxft").getPath() + "/voice.opus";
    /**
     * 采样率，现在能够保证在所有设备上使用的采样率是44100Hz, 但是其他的采样率（22050, 16000, 11025）在一些设备上也可以使用。
     */
    private static final int SAMPLE_RATE = 16000;
    private static final int QUEUE_SIZE = 1000;
    private ArrayBlockingQueue<byte[]> mAudioDataQueue;
    private ArrayBlockingQueue<byte[]> mAudioAdcDataQueue;

    private byte[] mAudioInBuffer;
    private int mAudioInBufferSize=640;

    private AudioPlayThread mAudioPlayThread;
    private VBRRecordThread mVbrRecordThread;
    private VBRAnalysisThread mVbrAnalysisThread;
    @RequiresApi(api = Build.VERSION_CODES.M)
    public void startVoiceToIntercom() {
        Log.e(TAG,"start voice to intercom");
//        if(MyDeviceManager.getInstance().getChooseDevice() == null || !MyDeviceManager.getInstance().isConnectDevice(MyDeviceManager.getInstance().getChooseDevice())){
//            Toast.makeText(App.getContext(), "当前暂无设备连接，请连接设备后再试", Toast.LENGTH_SHORT).show();
//            return false;
//        }
        isPlay = false;
        if (isPlay){
            Toast.makeText(this, "对讲接收中，请稍后", Toast.LENGTH_SHORT).show();
            return;
        }
        if (isRecord){
            Toast.makeText(this, "录制中，请勿重复点击", Toast.LENGTH_SHORT).show();
            return;
        }
        isRecord = true;
        if (mAudioPlayThread != null) {
            //若线程不为空,则中断线程
            mAudioPlayThread.interrupt();
            mAudioPlayThread = null;
        }

        sendCount = 0;
        opusCount = 0;
//        MyDeviceManager.getInstance().writeData(FxftProtocolUtil.getInstance().startVoiceData(), serviceUUID, writeUUID);
//        byte[] firstPage = FxftProtocolUtil.getInstance().dealVoiceData(OpusUtil.createFirstPage(),sendCount);
//        MyDeviceManager.getInstance().writeData(firstPage,serviceUUID,writeUUID);
        boolean sendFirstPacketResult = sendStartSoundRecording(OpusUtil.createFirstPage());
        if(!sendFirstPacketResult){
            Log.e(TAG,"发送第一个opus音频数据包失败");
            return;
        }
        sendCount +=1;
//        byte[] secondPage = FxftProtocolUtil.getInstance().dealVoiceData(OpusUtil.createSecondPage(),sendCount);
//        MyDeviceManager.getInstance().writeData(secondPage,serviceUUID,writeUUID);
        boolean sendSecondPacketResult = sendStartSoundRecording(OpusUtil.createSecondPage());
        if(!sendSecondPacketResult){
            Log.e(TAG,"发送第二个opus音频数据包失败");
            return;
        }
        sendCount +=1;

        if (mVbrRecordThread != null) {
            //若线程不为空,则中断线程
            mVbrRecordThread.interrupt();
            mVbrRecordThread = null;
        }
        mVbrRecordThread = new VBRRecordThread();
        mVbrRecordThread.start();

        if (mVbrAnalysisThread != null){
            mVbrAnalysisThread.interrupt();
            mVbrAnalysisThread = null;
        }
        mVbrAnalysisThread = new VBRAnalysisThread();
        mVbrAnalysisThread.start();

        Toast.makeText(this, "开始录音", Toast.LENGTH_SHORT).show();
    }


    public void stopVoiceToIntercom() {
        Log.e(TAG,"stop voice to intercom");
        if (!isRecord){
            Toast.makeText(this, "对讲已停止", Toast.LENGTH_SHORT).show();
            return;
        }
        if (null != mVbrRecordThread) {
            mVbrRecordThread.interrupt();
            mVbrRecordThread = null;
        }
        if (null != mVbrAnalysisThread) {
            mVbrAnalysisThread.interrupt();
            mVbrAnalysisThread = null;
        }

        isRecord = false;
        mAudioDataQueue.clear();

//        MyDeviceManager.getInstance().writeData(FxftProtocolUtil.getInstance().endVoiceData(), serviceUUID, writeUUID);
        if(!sendStopSoundRecording()){
            Log.e(TAG,"发送结束ppt按键音频数据包失败");
        }

        Toast.makeText(this, "结束录音", Toast.LENGTH_SHORT).show();
    }

    private class VBRRecordThread extends Thread{
        AudioRecord mAudioRecord;
        long mEncoderHandler;

        VBRRecordThread(){
            Log.i(TAG,"init VBRRecordThread");
            mEncoderHandler = JniClient.getInstance().createEncoder(SAMPLE_RATE,1,10,1,32000);
            /**
             * 获取音频缓冲最小的大小
             */
            mAudioDataQueue = new ArrayBlockingQueue<byte[]>(QUEUE_SIZE);

            mAudioInBuffer = new byte[mAudioInBufferSize];
            /**
             * 参数1：音频源
             * 参数2：采样率 主流是44100
             * 参数3：声道设置 MONO单声道 STEREO立体声
             * 参数4：编码格式和采样大小 编码格式为PCM,主流大小为16BIT
             * 参数5：采集数据需要的缓冲区大小
             */
            if (android.os.Build.VERSION.SDK_INT >= 16) {

                mAudioRecord = new AudioRecord(
                        MediaRecorder.AudioSource.MIC, SAMPLE_RATE,//VOICE_COMMUNICATION
                        AudioFormat.CHANNEL_IN_DEFAULT,//.CHANNEL_IN_STEREO,
                        AudioFormat.ENCODING_PCM_16BIT, mAudioInBufferSize);

            } else {
                mAudioRecord = new AudioRecord(
                        MediaRecorder.AudioSource.MIC, SAMPLE_RATE,
                        AudioFormat.CHANNEL_IN_DEFAULT,
                        AudioFormat.ENCODING_PCM_16BIT, mAudioInBufferSize);
            }
        }

        @Override
        public void run() {
            Log.e(TAG,"vbr record audio start");
            try {
                mAudioRecord.startRecording();
                byte[] tempBuffer;
                byte[] resultBuffer = new byte[1000];

                while (isRecord){
                    if (mAudioRecord != null){
                        mAudioRecord.read(mAudioInBuffer, 0, mAudioInBufferSize);
                        tempBuffer = mAudioInBuffer.clone();
//                        MyLogUtil.d(TAG, "PCM数据: " + tempBuffer.length);
//                        MyLogUtil.d(TAG, "PCM数据: " + ByteUtils.toHexString(tempBuffer));
                        int size = JniClient.getInstance().encode(mEncoderHandler,tempBuffer,resultBuffer);
                        if (size > 0){
                            byte[] tempEncodeBuffer = new byte[size];
                            System.arraycopy(resultBuffer,0,tempEncodeBuffer,0,size);
//                            MyLogUtil.d(TAG, "OPUS数据: " + tempEncodeBuffer.length);
                            try {
                                //根据OPUS协议，单个segment不超过255字节，故提前分片，并判断此分片的segment是否延续到下一页
                                if (size < 255){
                                    //TODO 停止时候会弹出异常，需要处理，但是不影响音频发送
                                    mAudioDataQueue.put(tempEncodeBuffer);
                                }else {
                                    int round = new BigDecimal(size).divide(new BigDecimal(255),BigDecimal.ROUND_DOWN).intValue();
                                    if (mAudioDataQueue.size() < 50 && mAudioDataQueue.size() + round > 50){
                                        isContinuePage = true;
                                    }
                                    for (int i = 0; i < round; i++){
                                        byte[] bytes = new byte[255];
                                        System.arraycopy(tempEncodeBuffer,i*255,bytes,0,255);
                                        mAudioDataQueue.put(bytes);
                                    }
                                    int leftSize = tempEncodeBuffer.length - round*255;
                                    byte leftBytes[] = new byte[leftSize];
                                    System.arraycopy(tempEncodeBuffer,round*255,leftBytes,0,leftSize);
                                    mAudioDataQueue.put(leftBytes);
                                }
                            }catch (Exception e){
                                e.printStackTrace();
                                Log.e(TAG,"put record voice data error : " + e.getMessage());
                            }
                        }else {
                            Log.e(TAG,"audio encode fail : " + size);
                        }
                    }
                }

                mAudioRecord.stop();
                mAudioRecord.release();
                JniClient.getInstance().destroyEncoder(mEncoderHandler);
                isRecord = false;
            }catch (Exception e){
                e.printStackTrace();
                Log.e(TAG,"record error : " + e.getMessage());
                JniClient.getInstance().destroyEncoder(mEncoderHandler);
                isRecord = false;
            }
        }
    }
    private class VBRAnalysisThread extends Thread{
        @RequiresApi(api = Build.VERSION_CODES.M)
        VBRAnalysisThread(){
            setPriority(NORM_PRIORITY);
            Log.i(TAG,"init VBRSendThread");
        }

        List<byte[]> voiceData;

        @Override
        public void run() {
            Log.e(TAG,"send vbr audio start");

            while (isRecord || mAudioDataQueue.size() > 0){
                try {
                    if (mAudioDataQueue.size() < 50){
                        continue;
                    }
                    voiceData = new ArrayList<>();
                    for (int i = 0; i < 50; i++){
                        voiceData.add(mAudioDataQueue.take());
                    }

                    //每50个音频数据（segment）为一页，每页开始发送头数据（因。
                    //第一第二页为固定内容，音频数据从第三页开始，页数下标从0开始，故+2；
                    int pageNum = opusCount + 2;
                    byte[] opusData = OpusUtil.createPageData(voiceData,isContinuePage?OpusUtil.HEADER_TYPE_FLAG_CONTINUE:OpusUtil.HEADER_TYPE_FLAG_OTHER,pageNum);
                    opusCount++;
//                    sendOpusData(opusData);
                    int length = 400;
                    if (opusData.length < length){
                        sendStartSoundRecording(opusData);
//                        MyDeviceManager.getInstance().writeData(FxftProtocolUtil.getInstance().dealVoiceData(opusData,sendCount),serviceUUID,writeUUID);
                        sendCount +=1;
                    }else {
                        int round = new BigDecimal(opusData.length).divide(new BigDecimal(length),BigDecimal.ROUND_DOWN).intValue();
                        Log.e(TAG,"opus data round : " + round + " - data length : " + opusData.length + " - sendCount : " + sendCount);
                        for (int i = 0; i < round; i++){
                            byte[] tempData = new byte[length];
                            System.arraycopy(opusData,i*length,tempData,0,length);
                            sleep(10);
                            sendStartSoundRecording(tempData);
//                            MyDeviceManager.getInstance().writeData(FxftProtocolUtil.getInstance().dealVoiceData(tempData,sendCount),serviceUUID,writeUUID);
                            sendCount +=1;
                        }
                        int leftSize = opusData.length - round*length;
                        byte leftBytes[] = new byte[leftSize];
                        System.arraycopy(opusData,round*length,leftBytes,0,leftSize);
                        sleep(10);
                        sendStartSoundRecording(leftBytes);
//                        MyDeviceManager.getInstance().writeData(FxftProtocolUtil.getInstance().dealVoiceData(leftBytes,sendCount),serviceUUID,writeUUID);
                        sendCount +=1;
                        Log.e(TAG,"left size : " + leftSize + " - sendCount : " + sendCount);
                    }
                }catch (Exception e){
                    e.printStackTrace();
                    Log.e(TAG,"send error : " + e.getMessage());
                    sendCount = 0;
                    opusCount = 0;
                }
            }
        }
    }

    /**
     * 解析音频数据
     */
    private void analysisData(byte[] soundData){
        //1、拿到音频数据
        byte[] soudDataBytes = DataPackage.getPacketDataLength(soundData);
        int soudDataLength = HexUtil.byteToShortLittle(soudDataBytes);
        Log.e(TAG,"音频数据长度 = " + soudDataLength);
        byte[] soudDataArray = new byte[soudDataLength];
        System.arraycopy(soundData,8,soudDataArray,0,soudDataLength);
        Log.e(TAG,"准备播放音频数据长度 = " + soudDataArray.length);
        analysisVoiceData(soudDataArray);
    }

    /**
     * 开启线程播放音频数据
     * @param data
     */
    private void analysisVoiceData(byte[] data){
//        MyLogUtil.d(TAG,"analysisVoiceData：" + ByteUtils.toHexString(data));
        Log.e(TAG,"开启线程播放音频数据，当前播放状态 isPlay = " + isPlay);
        if (!isPlay){
            isPlay = true;
            mAudioPlayThread = new AudioPlayThread();
            mAudioPlayThread.start();
        }
        getVoice(data);
    }
    private ThreadPoolExecutor audioReceivePoolExecutor = new ThreadPoolExecutor(
            1, 1, 1,
            TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<Runnable>(),
            new ThreadPoolExecutor.DiscardPolicy()
    );

    /**
     * 播放音频数据
     */
    private class AudioPlayThread extends Thread {
        AudioTrack mAudioTrack;
        long mDecoderHandler;

        AudioPlayThread(){
            Log.e(TAG,"当前线程 = " + Thread.currentThread());
            setPriority(MAX_PRIORITY);
            mAudioAdcDataQueue = new ArrayBlockingQueue<>(QUEUE_SIZE);
            int minBufferSize = AudioRecord.getMinBufferSize(SAMPLE_RATE, AudioFormat.CHANNEL_IN_DEFAULT, AudioFormat.ENCODING_PCM_16BIT);
            mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,SAMPLE_RATE,AudioFormat.CHANNEL_IN_DEFAULT,
                    AudioFormat.ENCODING_PCM_16BIT,minBufferSize,AudioTrack.MODE_STREAM);
            mDecoderHandler = JniClient.getInstance().createDecoder(SAMPLE_RATE,1);
        }

        @Override
        public void run() {

            try {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                mAudioTrack.play();

                int samples = 0;
                byte[] originalData = new byte[0];
                int index = 0;
//                boolean needFinish = false;
                Log.e(TAG,"------------------开始播放------------，isPlay = " + isPlay);
                while (isPlay && (index < originalData.length || mAudioAdcDataQueue.size() > 0)){
                    Log.e(TAG,"------------------开始播放------------，mAudioAdcDataQueue.size() = " + mAudioAdcDataQueue.size());
                    if (mAudioTrack != null && mAudioAdcDataQueue.size() > 0){
                        while (originalData.length < index + 27 && mAudioAdcDataQueue.size() > 0){
//                            byte[] tempBytes = mAudioAdcDataQueue.take();
//                            byte finishMark = tempBytes[1];
//                            if (finishMark == ((byte) 0x01)){
//                                needFinish = true;
//                            }else {
//                                needFinish = false;
//                            }
//                            Log.i(TAG,"1finishMark : " + finishMark + " - needFinish : " + needFinish);
//                            int voiceLength = ByteUtils.byteToInt(new byte[]{tempBytes[5],tempBytes[4]},0);
////                            int voiceLength = 0;
//                            totalLength += voiceLength;
//                            byte[] voiceData = new byte[voiceLength];
//                            System.arraycopy(tempBytes,6,voiceData,0,voiceLength);
//                            Log.i(TAG,"1originalData length - " + originalData.length + " - index - " + index + " - voiceData : " + ByteUtils.toHexString(voiceData));
                            originalData = ByteUtils.concat(originalData,mAudioAdcDataQueue.take());
//                            MyLogUtil.i(TAG,"1originalData length - " + originalData.length + " - index - " + index + " - originalData : " + ByteUtils.toHexString(originalData));
                        }
                        Log.e(TAG,"----------------------------------开始打印日志------------------------------------");
                        if (originalData.length < index + 27){
                            Log.e(TAG,"need to continue 1");
                            continue;
                        }
                        byte[] capturePattern = new byte[4];
                        System.arraycopy(originalData,index,capturePattern,0,4);
                        Log.e(TAG,"opus capturePattern : " + ByteUtils.toHexString(capturePattern));
                        index +=4;

                        byte[] streamStructureVersion = new byte[1];
                        System.arraycopy(originalData,index,streamStructureVersion,0,1);
                        Log.e(TAG,"opus streamStructureVersion : " + ByteUtils.toHexString(streamStructureVersion));
                        index +=1;

                        byte[] headerTypeFlag = new byte[1];
                        System.arraycopy(originalData,index,headerTypeFlag,0,1);
                        Log.e(TAG,"opus headerTypeFlag : " + ByteUtils.toHexString(headerTypeFlag));
                        index +=1;

                        byte[] granulePosition = new byte[8];
                        System.arraycopy(originalData,index,granulePosition,0,8);
                        Log.e(TAG,"opus granulePosition : " + ByteUtils.toHexString(granulePosition));
                        index +=8;

                        byte[] serialNumber = new byte[4];
                        System.arraycopy(originalData,index,serialNumber,0,4);
                        Log.e(TAG,"opus serialNumber : " + ByteUtils.toHexString(serialNumber));
                        index +=4;

                        byte[] pageSequenceNumber = new byte[4];
                        System.arraycopy(originalData,index,pageSequenceNumber,0,4);
                        Log.e(TAG,"opus pageSequenceNumber : " + ByteUtils.toHexString(pageSequenceNumber));
                        index +=4;

                        byte[] crcCheckSum = new byte[4];
                        System.arraycopy(originalData,index,crcCheckSum,0,4);
                        Log.e(TAG,"opus crcCheckSum : " + ByteUtils.toHexString(crcCheckSum));
                        index +=4;

                        byte[] numberPageSegments = new byte[1];
                        System.arraycopy(originalData,index,numberPageSegments,0,1);
                        index +=1;
                        Log.e(TAG,"opus numberPageSegments : " + ByteUtils.toHexString(numberPageSegments));


                        Log.e(TAG,"----------------------------------结束打印日志------------------------------------");
                        byte[] number = new byte[]{0x00,numberPageSegments[0]};
                        int segmentTableNumber = ByteUtils.byteToInt(number,0);
                        Log.e(TAG,"opus segmentTableNumber : " + segmentTableNumber);

                        while (originalData.length < index + segmentTableNumber && mAudioAdcDataQueue.size() > 0){
                            byte[] tempBytes = mAudioAdcDataQueue.take();
//                            byte finishMark = tempBytes[1];
//                            if (finishMark == ((byte) 0x01)){
//                                needFinish = true;
//                            }else {
//                                needFinish = false;
//                            }
//                            Log.i(TAG,"2finishMark : " + finishMark + " - needFinish : " + needFinish);
//                            int voiceLength = ByteUtils.byteToInt(new byte[]{tempBytes[5],tempBytes[4]},0);
//                            totalLength += voiceLength;
//                            byte[] voiceData = new byte[voiceLength];
//                            System.arraycopy(tempBytes,6,voiceData,0,voiceLength);
//                            Log.i(TAG,"2originalData length - " + originalData.length + " - index - " + index + " - voiceData : " + ByteUtils.toHexString(voiceData));
                            originalData = ByteUtils.concat(originalData,tempBytes);
//                            MyLogUtil.i(TAG,"2originalData length - " + originalData.length + " - index - " + index + " - originalData : " + ByteUtils.toHexString(originalData));
                        }
                        if (originalData.length < index + segmentTableNumber){
                            Log.e(TAG,"need to continue 2");
                            continue;
                        }

                        byte[] segmentTable = new byte[segmentTableNumber];
                        System.arraycopy(originalData,index,segmentTable,0,segmentTableNumber);
                        index +=segmentTableNumber;
                        Log.e(TAG,"opus segmentTable : " + ByteUtils.toHexString(segmentTable));

                        for (int i=0; i<segmentTableNumber; i++){
                            byte[] length = new byte[]{0x00,segmentTable[i]};
                            int pageDataLength = ByteUtils.byteToInt(length,0);
                            Log.e(TAG,"opus pageDataLength : " + pageDataLength);
                            while (originalData.length < index + pageDataLength){
                                if (mAudioAdcDataQueue.size() > 0){
                                    byte[] tempBytes = mAudioAdcDataQueue.take();
//                                    byte finishMark = tempBytes[1];
//                                    if (finishMark == ((byte) 0x01)){
//                                        needFinish = true;
//                                    }else {
//                                        needFinish = false;
//                                    }
//                                    Log.i(TAG,"3finishMark : " + finishMark + " - needFinish : " + needFinish);
//                                    int voiceLength = ByteUtils.byteToInt(new byte[]{tempBytes[5],tempBytes[4]},0);
//                                    totalLength += voiceLength;
//                                    byte[] voiceData = new byte[voiceLength];
//                                    System.arraycopy(tempBytes,6,voiceData,0,voiceLength);
//                                    Log.i(TAG,"3originalData length - " + originalData.length + " - index - " + index + " - voiceData : " + ByteUtils.toHexString(voiceData));
                                    originalData = ByteUtils.concat(originalData,tempBytes);
                                }
//                                else if (needFinish){
//                                    Log.e(TAG,"need finish play thread1");
//                                    mAudioPlayThread.interrupt();
//                                    mAudioPlayThread = null;
//                                }
//                                MyLogUtil.i(TAG,"3originalData length - " + originalData.length + " - index - " + index + " - originalData : " + ByteUtils.toHexString(originalData));
                            }
                            byte[] pageData = new byte[pageDataLength];
                            System.arraycopy(originalData,index,pageData,0,pageDataLength);
                            index +=pageDataLength;
                            Log.e(TAG,"opus pageData length - " + pageData.length + " - index - " + index + " - value :" + ByteUtils.toHexString(pageData));
                            byte[] decodeBufferArray = new byte[SAMPLE_RATE];
                            int size = JniClient.getInstance().decode(mDecoderHandler,pageData,decodeBufferArray);
                            if (size > 0){
                                byte[] resultArray = new byte[size*2];
                                System.arraycopy(decodeBufferArray,0,resultArray,0,size*2);
                                mAudioTrack.write(resultArray,0,resultArray.length);
                                Log.e(TAG,"result size : " + size + "-resultArray size : " + resultArray.length);
                                samples += size;
                            }else {
                                Log.e(TAG,"OpusFileDecoder error : " + size);
                            }
                            int duration = samples/SAMPLE_RATE;
                            Log.e(TAG,"duration : " + duration);
                        }
//                        if (needFinish){
//                            Log.e(TAG,"need finish play thread2");
//                            mAudioPlayThread.interrupt();
//                            mAudioPlayThread = null;
//                        }
                    }
                }
                Log.e(TAG,"-------------音频播放完成，清空状态--------------------");
//                mAudioTrack.stop();
//                mAudioTrack.release();
//                mAudioAdcDataQueue.clear();
//                JniClient.getInstance().destroyDecoder(mDecoderHandler);
//                isPlay = false;
//                totalLength = 0;
            }catch (Exception e){
                e.printStackTrace();
                Log.e(TAG,"run error : " + e.getMessage());

            }finally {
                Log.e(TAG,"-------------音频播放完成，执行一定清空状态--------------------");
                mAudioTrack.stop();
                mAudioTrack.release();
                mAudioAdcDataQueue.clear();
                JniClient.getInstance().destroyDecoder(mDecoderHandler);
                isPlay = false;
                totalLength = 0;
            }
        }
    }


    /**
     * 音频数据加入队列
     * @param data
     */
    public void getVoice(byte[] data) {
        try {
            Log.e(TAG,"音频数据长度 = " + data.length + " ，加入队列");
            mAudioAdcDataQueue.put(data);
        }catch (Exception e){
            e.printStackTrace();
            Log.e(TAG,"put play voice data error : " + e.getMessage());
        }
    }


//    public void sendCmdData(byte[] data) {
//        if (MyDeviceManager.getInstance().getChooseDevice() != null && MyDeviceManager.getInstance().isConnectDevice(MyDeviceManager.getInstance().getChooseDevice())){
//            MyDeviceManager.getInstance().writeData(data,serviceUUID,writeUUID);
//        }else {
//            Toast.makeText(this, "蓝牙设备未连接", Toast.LENGTH_SHORT).show();
//        }
//    }



}